A “data type” or simply “type” in computer programs is a classification identifying one of various types of data, such as integer or Boolean, that determines the possible values for that type; the operations that can be done on values of that type; the meaning of the data; and the way values of that type can be stored. An example of a type would be an “int”, which, in C-like languages, typically represents a signed 32-bit integer. As such, an “int” would not be able to hold text values. If it did, it would violate fundamental assumptions made by the program and compiler. For example, an “int” would typically allow the subtraction operation, and text values may not support such a subtraction operation. Therefore, types and data have to be checked to ensure they conform to the “rules” of the programming language in a process known as “type checking.”
Static type checking is a form of type checking which occurs at compile time. Therefore, while the program is being transformed from source code to its target by the compiler, it is also type checked. If the type checking fails, the compiler may reject the program and not transform the source code to its desired target.
In contrast, dynamic type checking occurs at runtime, or, in other words, during program execution. If a type check fails at runtime, the program may produce a runtime error and terminate. For complex and mission-critical applications, static type checking would be strongly preferred because there is certainty and predictability the program will not terminate due to a possible type error at runtime. Therefore, where stability and correctness are preferred or even needed, static type checking is the preferred option.
Further, a programming language which is “dynamically-typed” may not necessarily be dynamically type checked. For instance, type information may not be available until runtime (dynamic typing), but if type incompatibilities occur at runtime, the program may choose to silently resolve the error and continue (meaning it is not dynamically type-checked). Some programming languages may perform no type checking or limited type checking.
For example, the JavaScript language will throw a runtime TypeError when trying to call a numeric literal as a function like so (but only once it's encountered at runtime): 2( );
Meanwhile, operations on seemingly incompatible types will silently succeed or fail:
1+“1”==“11” // addition of number and string
1+“a”==“1a” // addition of number and string
1−“a”==NaN // IEEE 754 NaN (“Not a Number”) type
This behavior is very unintuitive to most programmers, and lack of type checking can make writing robust applications very difficult. For applications with large code bases, it becomes cumbersome and nearly impossible to find, analyze, or anticipate potential runtime type errors, which can cause the application to crash or behave unexpectedly. For a language like JavaScript, which powers most of the modern websites, this is not a desirable situation.
Type safety is the extent to which a programming language or compiler discourages or prevents type errors. Aforementioned examples also illustrate the concept of “type safety”, or the lack thereof. As illustrated, JavaScript is not type safe.
Microsoft's “TypeScript” programming language provides means to interoperate with JavaScript, but suffers from an inelegant, unintuitive design which hampers programmer productivity. For example, Microsoft's TypeScript requires developers to manually provide type annotations for JavaScript code and libraries. For larger libraries, this could consume many months of developer effort. Furthermore, the correctness of these type annotations are not verified, and, in some cases, they can be very difficult to verify.
The “Roy” programming language by Brian McKenna can also interoperate with JavaScript. In “Roy”, it is assumed that an unknown identifier refers to a native JavaScript global. This method suffers from being unable to distinguish between a variable declared from JavaScript, a variable that was not declared inside the compatible programming language (in this case, inside Roy), and a variable that was not declared at all (in this case, in either Roy or JavaScript). This can lead to a program with unexpected and unpredictable behaviors.